﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Qing.Lang;
using Qing.Proto;

namespace Qing.Std {

    class Cost : Native {
        public override string Name { get; set; } = "计时";
        public override string Desc { get; set; } = "参数1-代码块，返回小数；执行参数1代码块，返回执行耗时";
        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count == 0) {
                return Expr.Err("计时函数调用参数不足");
            }
            if (args[0].Tp != TP.Brace) {
                return Expr.Err("计时函数的参数必须是代码块");
            }

            long start = DateTime.Now.ToUniversalTime().Ticks;
            Expr.EvalExprs(args[0].List!, ctx);
            long end = DateTime.Now.ToUniversalTime().Ticks;

            return new Expr(TP.Float, Convert.ToDecimal(end - start) / 10000000);
        }

    }


    class Now : Native {
        public override string Name { get; set; } = "系统时间";
        public override string Desc { get; set; } = "无参，返回对象；获取当前系统时间，返回时间对象";
        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            
            return new Expr(TP.Obj, new DateObj(DateTime.Now));
           
        }

    }

    class Sleep : Native {
        public override string Name { get; set; } = "休眠";
        public override string Desc { get; set; } = "参数1-整数，返回空；线程休眠参数1指定的时间，单位是毫秒";
        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count > 0 && args[0].Tp == TP.Int) {
                Thread.Sleep(args[0].Int());
                return new Expr();
            } 
            return Expr.Err("休眠函数参数错误");
        }

    }


    class Timer : Native {
        public override string Name { get; set; } = "定时任务";
        public override string Desc { get; set; } = "参数1-整数，参数2-代码块，返回定时任务；创建一个定时任务，参数1指定时间间隔，每次执行参数2代码块";
        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count > 1 && args[0].Tp == TP.Int && args[1].Tp == TP.Brace) {
                bool ignoreErr = true;
                if(args.Count > 2) {
                    ignoreErr = args[2].ToBool();
                }
                return new Expr(TP.Timer, new Lang.Timer(args[0].Int(), args[1].List!, ctx, ignoreErr));
            }
            return Expr.Err("定时任务函数参数错误");
        }

    }

    class TimerStart : Native {
        public override string Name { get; set; } = "启动定时任务";
        public override string Desc { get; set; } = "参数1-定时任务，返回空；启动参数1对应的定时任务";
        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count > 0 && args[0].Tp == TP.Timer) {
                args[0].Timer().T.Start();
                return new Expr();
            }
            return Expr.Err("启动定时任务函数参数错误");
        }

    }

    class TimerStop : Native {
        public override string Name { get; set; } = "停止定时任务";
        public override string Desc { get; set; } = "参数1-定时任务，返回空；停止参数1对应的定时任务";
        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count > 0 && args[0].Tp == TP.Timer) {
                args[0].Timer().T.Stop();
                return new Expr();
            }
            Env.Timers.Remove(args[0].Timer().T);
            return Expr.Err("停止定时任务函数参数错误");
        }

    }

    class TimeoutTask : Native {
        public override string Name { get; set; } = "延时任务";
        public override string Desc { get; set; } = "参数1-整数，参数2-代码块，返回延时任务；创建一个延时任务，参数1指定延迟时间，然后执行参数2代码块";
        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count > 1 && args[0].Tp == TP.Int && args[1].Tp == TP.Brace) {
                int timeout = args[0].Int();
                List<Expr> code = args[1].List!;
                Task.Run(async () => {
                    await Task.Delay(timeout);
                    Expr.EvalExprs(code, ctx);
                });
                return new Expr();
            }
            return Expr.Err("延时任务函数参数错误");
        }

    }

    class WaitTask : Native {
        public override string Name { get; set; } = "等待任务";
        public override string Desc { get; set; } = "参数1-任务，可选参数2-整数，返回任意；等待一个异步任务，如果传入参数2可指定最大等待时长（默认无限等待），等待结束后如果未超时返回任务结果，否则返回任务本身";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count > 0 && args[0].Tp == TP.Task ) {
                int timeout = 30000;
                if(args.Count > 1 && args[1].Tp == TP.Int) {
                    timeout = args[1].Int();
                }

                Task<Expr> t = args[0].Task();

                Task.WaitAll(new Task[] { t }, timeout);
                if (t.IsCompleted) {
                    return t.Result;
                } else {
                    return args[0];
                }
               
            }
            return Expr.Err("等待任务函数参数错误");
        }

    }


}
